﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Tests
//  File name:	TestCaching.cs
//  Developer:	Solomatov Igor
//  Created:	03.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System;
using System.Threading;
using System.Web.Caching;
using Microsoft.SharePoint;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Smart.Common;

namespace Smart.Documents.Tests
{
	[TestClass]
	public class TestCaching
	{
		[TestMethod]
		public void CacheFactory()
		{
			string k1 = null;
			string k2 = null;
			string k3 = null;
			string k4 = null;
			string k5 = null;
			string k6 = null;
			string k7 = null;
			string k8 = null;
			string k9 = null;
			string k10 = null;

			string v1 = null;
			string v2 = null;
			string v3 = null;
			string v4 = null;
			string v5 = null;
			string v6 = null;
			string v7 = null;
			string v8 = null;
			string v9 = null;
			string v10 = null;
			string v11 = null;

			bool IsNull = false;

			var res = SPH.RunUnder("http://localhost:777/",
								   delegate
								   {
									   var factory = SPServices.Cache;

									   IsNull = factory.MainCache == null || factory.RequestStore == null;

									   factory.Clear();

									   k1 = factory.GetKey(new object[] { "k1", Guid.Empty }, true, false, false, false, null, null);
									   k2 = factory.GetKey(new object[] { "k1", Guid.Empty }, true, false, false, false, null, null);
									   k3 = factory.GetKey(new object[] { "k2", Guid.Empty }, true, false, false, false, null, null);
									   k4 = factory.GetKey(new object[] { "k1", Guid.NewGuid() }, true, false, false, false, null, null);
									   k5 = factory.GetKey(new object[] { "k1", Guid.Empty }, true, false, true, false, null, null);
									   k6 = factory.GetKey(new object[] { "k1", Guid.Empty }, true, true, false, false, null, null);
									   k7 = factory.GetKey(new object[] { "k1", Guid.Empty }, true, true,
														   false, false, "<Where><And><Eq><FieldRef Name=\"Title\"><Value Type=\"Text\">xxx</Value></Eq></And></Where>", null);
									   k8 = factory.GetKey(new object[] { "k1", Guid.Empty }, true, true,
														   false, false, "<Where><And><Eq><FieldRef Name=\"Title\"><Value Type=\"Text\">yyy</Value></Eq></And></Where>", null);
									   k9 = factory.GetKey(new object[] { "k1", Guid.Empty }, true, true,
														   false, false, "<Where><And><Eq><FieldRef Name=\"title\"><Value Type=\"Text\">xxx</Value></Eq></And></Where>", null);
									   k10 = factory.GetKey(new object[] { "k1", Guid.Empty }, true, true,
															false, false, "<Where><And><Eq><FieldRef Name=\"name\"><Value Type=\"Text\">xxx</Value></Eq></And></Where>", null);

									   v1 = (string)factory.Get(k1, "dv1");

									   factory.Set(k1, "v2", new TimeSpan(0, 0, 0, 5), CacheItemPriority.Default);

									   v2 = (string)factory.Get(k1, "dv2");

									   factory.Set(k1, "v3", new TimeSpan(0, 0, 0, 5), CacheItemPriority.Default);

									   v3 = (string)factory.Get(k1, "dv3");

									   factory.Set(k3, "v4", new TimeSpan(0, 0, 0, 5), new TimeSpan(0, 0, 0, 5),
												   CacheItemPriority.Default);

									   v4 = (string)factory.Get(k3, "dv4");

									   factory.Remove(k1);

									   v5 = (string)factory.Get(k1, "dv5");

									   factory.Set("rv1", "rv1", new TimeSpan(0, 0, 0, 5), new TimeSpan(0, 0, 0, 5),
												   CacheItemPriority.Default);
									   factory.Set("rv2", "rv2", new TimeSpan(0, 0, 0, 5), new TimeSpan(0, 0, 0, 5),
												   CacheItemPriority.Default);
									   factory.Set("rv3", "rv3", new TimeSpan(0, 0, 0, 5), CacheItemPriority.Default);

									   factory.RemoveKeys("rv");

									   v6 = (string)factory.Get(k3, "dv6");

									   v7 =
										   (string)factory.Get("rv1", "dv7") +
										   (string)factory.Get("rv2", "dv7") +
										   (string)factory.Get("rv3", "dv7");

									   v8 = (string)factory.GetRequestItem(k1, () => "v8");
									   v9 = (string)factory.GetRequestItem(k1, () => "dv9");

									   factory.Clear();

									   v10 = (string)factory.Get(k3, "dv10");
									   v11 = (string)factory.GetRequestItem(k1, () => "dv11");
								   });

			Assert.AreEqual(true, res, "SPH.RunUnder completed with errors!");

			Assert.AreEqual(false, IsNull, "factory.MainCache or factory.RequestStore is null");

			Assert.AreEqual(k1, k2, "factory.GetKey should generate equal keys!");
			Assert.AreNotEqual(k1, k3, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k1, k4, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k3, k4, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k1, k5, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k1, k6, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k4, k6, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k5, k6, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k1, k7, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k4, k7, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k5, k7, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k6, k7, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k1, k8, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k4, k8, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k5, k8, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k6, k8, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k7, k8, "factory.GetKey should generate different keys!");
			Assert.AreEqual(k7, k9, "factory.GetKey should generate equal keys!");
			Assert.AreNotEqual(k1, k10, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k4, k10, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k5, k10, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k6, k10, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k7, k10, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k8, k10, "factory.GetKey should generate different keys!");
			Assert.AreNotEqual(k9, k10, "factory.GetKey should generate different keys!");

			Assert.AreEqual("dv1", v1);
			Assert.AreEqual("v2", v2);
			Assert.AreEqual("v3", v3);
			Assert.AreEqual("v4", v4);
			Assert.AreEqual("dv5", v5);
			Assert.AreEqual(v4, v6);
			Assert.AreEqual("dv7dv7dv7", v7);
			Assert.AreEqual("v8", v8);
			Assert.AreEqual("v8", v9);
			Assert.AreEqual("dv10", v10);
			Assert.AreEqual("dv11", v11);
		}

		[TestMethod]
		public void CacheEntry()
		{
			string c1 = null;
			string c2 = null;
			string c3 = null;
			string c4 = null;
			string c5 = null;
			string c6 = null;
			string c7 = null;
			string c8 = null;
			string c9 = null;
			string c10 = null;
			string c11 = null;

			var res = SPH.RunUnder("http://localhost:777/",
								   delegate
								   {
									   SPServices.Cache.Clear();

									   var v1 = new CacheEntry<string>("k1")
												   {
													   UserDependent = false,
													   UrlDependent = false,
													   WebDependent = false,
													   Timeout = new TimeSpan(0, 0, 0, 5),
													   Default = "dv1"
												   };
									   var v2 = new CacheEntry<string>("k1")
												   {
													   UserDependent = true,
													   UrlDependent = false,
													   WebDependent = false,
													   Timeout = new TimeSpan(0, 0, 0, 5),
													   Default = "dv2"
												   };
									   var v3 = new CacheEntry<string>("k1")
												   {
													   UserDependent = false,
													   UrlDependent = true,
													   WebDependent = false,
													   Timeout = new TimeSpan(0, 0, 0, 5),
													   Default = "dv3"
												   };
									   var v4 = new CacheEntry<string>("k1")
												   {
													   UserDependent = false,
													   UrlDependent = false,
													   WebDependent = true,
													   Timeout = new TimeSpan(0, 0, 0, 5),
													   Default = "dv4"
												   };
									   var v5 = new CacheEntry<string>("k1")
												   {
													   UserDependent = false,
													   UrlDependent = false,
													   WebDependent = false,
													   Timeout = new TimeSpan(0, 0, 0, 5),
													   Default = "dv5"
												   };

									   c1 = v1.Value;
									   v1.Value = "v1";
									   c2 = v1.Value;

									   c3 =
										   (v1.GetFullKey() != v2.GetFullKey()).ToString() +
										   (v1.GetFullKey() != v3.GetFullKey()) +
										   (v1.GetFullKey() != v4.GetFullKey()) +
										   (v1.GetFullKey() == v5.GetFullKey()) +
										   (v2.GetFullKey() != v3.GetFullKey()) +
										   (v2.GetFullKey() != v4.GetFullKey()) +
										   (v3.GetFullKey() != v4.GetFullKey());

									   v2.Value = "v2";
									   v3.Value = "v3";
									   v4.Value = "v4";

									   c4 = (v2.Value == "v2").ToString() + (v3.Value == "v3") + (v4.Value == "v4");

									   v2.RemoveFromCache();
									   v3.RemoveFromCache();
									   v4.Update();

									   c5 = (v2.Value == "dv2").ToString() + (v3.Value == "dv3") + (v4.Value == "v4");

									   v2.Value = "mv2";
									   v4.Value = "mv4";

									   c6 = (v2.Value == "mv2").ToString() + (v3.Value == "dv3") + (v4.Value == "mv4");

									   c7 =
										   (v1.Value != v2.Value).ToString() +
										   (v1.Value != v3.Value) +
										   (v1.Value != v4.Value) +
										   (v1.Value == v5.Value) +
										   (v2.Value != v3.Value) +
										   (v2.Value != v4.Value) +
										   (v3.Value != v4.Value);

									   v2 = new CacheEntry<string>("k1")
											   {
												   UserDependent = true,
												   UrlDependent = false,
												   WebDependent = false,
												   Timeout = new TimeSpan(0, 0, 0, 5),
												   Default = "dv2"
											   };

									   c8 = v2.Value;

									   // Init value
									   var v6 = new CacheEntry<string>("k6")
												   {
													   UserDependent = false,
													   UrlDependent = false,
													   WebDependent = false,
													   Timeout = new TimeSpan(0, 0, 0, 2),
													   SlidingExpiration = new TimeSpan(0, 0, 0, 1, 500),
													   Default = "dv6"
												   };

									   v6.Value = "v6";

									   c9 = v6.Value;

									   // TTL: Absolute 1300ms, Sliding 800ms
									   Thread.Sleep(700);

									   v6 = new CacheEntry<string>("k6")
											   {
												   UserDependent = false,
												   UrlDependent = false,
												   WebDependent = false,
												   Timeout = new TimeSpan(0, 0, 0, 2),
												   SlidingExpiration = new TimeSpan(0, 0, 0, 1, 500),
												   Default = "dv6"
											   };

									   c9 += v6.Value;

									   // TTL: Absolute 600ms, Sliding 800ms
									   Thread.Sleep(700);

									   v6 = new CacheEntry<string>("k6")
											   {
												   UserDependent = false,
												   UrlDependent = false,
												   WebDependent = false,
												   Timeout = new TimeSpan(0, 0, 0, 2),
												   SlidingExpiration = new TimeSpan(0, 0, 0, 1, 500),
												   Default = "dv6"
											   };

									   c9 += v6.Value;

									   // TTL: Absolute -200ms, Sliding 700ms
									   Thread.Sleep(800);

									   v6 = new CacheEntry<string>("k6")
											   {
												   UserDependent = false,
												   UrlDependent = false,
												   WebDependent = false,
												   Timeout = new TimeSpan(0, 0, 0, 2),
												   SlidingExpiration = new TimeSpan(0, 0, 0, 1, 500),
												   Default = "dv6"
											   };

									   c9 += v6.Value;

									   // Init value
									   var v7 = new CacheEntry<string>("k7")
												   {
													   UserDependent = false,
													   UrlDependent = false,
													   WebDependent = false,
													   Timeout = new TimeSpan(0, 0, 0, 2),
													   SlidingExpiration = new TimeSpan(0, 0, 0, 1, 500),
													   Default = "dv7"
												   };

									   v7.Value = "v7";

									   c10 = v7.Value;

									   // TTL: Absolute 400ms, Sliding -200ms
									   Thread.Sleep(1700);

									   v7 = new CacheEntry<string>("k7")
											   {
												   UserDependent = false,
												   UrlDependent = false,
												   WebDependent = false,
												   Timeout = new TimeSpan(0, 0, 0, 2),
												   SlidingExpiration = new TimeSpan(0, 0, 0, 1, 500),
												   Default = "dv7"
											   };

									   c10 += v7.Value;

									   var v8 = new CacheEntry<string, string>("k8")
												   {
													   UserDependent = false,
													   UrlDependent = false,
													   WebDependent = false,
													   Timeout = new TimeSpan(0, 0, 0, 2),
													   SlidingExpiration = new TimeSpan(0, 0, 0, 1, 500),
													   DefaultValue = "dv8"
												   };

									   c11 = v8["notexistingkey"];
									   v8["key"] = "v8";
									   c11 += v8["key"];

									   v8["notexistingkey"] = "notexistingvalue";

									   v8 = new CacheEntry<string, string>("k8")
											   {
												   UserDependent = false,
												   UrlDependent = false,
												   WebDependent = false,
												   Timeout = new TimeSpan(0, 0, 0, 2),
												   SlidingExpiration = new TimeSpan(0, 0, 0, 1, 500),
												   DefaultValue = "dv8"
											   };

									   v8.Remove("notexistingkey");

									   c11 += v8["notexistingkey"];
									   c11 += v8["key"];

									   // TTL: Abs 1300ms, Sliding 800ms
									   Thread.Sleep(700);

									   v8["key"] = "mv8";

									   // TTL: Abs 500ms, Sliding 700ms
									   Thread.Sleep(800);

									   v8 = new CacheEntry<string, string>("k8")
											   {
												   UserDependent = false,
												   UrlDependent = false,
												   WebDependent = false,
												   Timeout = new TimeSpan(0, 0, 0, 2),
												   SlidingExpiration = new TimeSpan(0, 0, 0, 1, 500),
												   DefaultValue = "dv8"
											   };

									   c11 += v8["key"];

									   // TTL: Abs -300ms, Sliding 700ms
									   Thread.Sleep(800);

									   v8 = new CacheEntry<string, string>("k8")
											   {
												   UserDependent = false,
												   UrlDependent = false,
												   WebDependent = false,
												   Timeout = new TimeSpan(0, 0, 0, 2),
												   SlidingExpiration = new TimeSpan(0, 0, 0, 1, 500),
												   DefaultValue = "dv8"
											   };

									   c11 += v8["key"];
								   });

			Assert.AreEqual(true, res, "SPH.RunUnder completed with errors!");

			Assert.AreEqual("dv1", c1);
			Assert.AreEqual("v1", c2);
			Assert.AreEqual("TrueTrueTrueTrueTrueTrueTrue", c3);
			Assert.AreEqual("TrueTrueTrue", c4);
			Assert.AreEqual("TrueTrueTrue", c5);
			Assert.AreEqual("TrueTrueTrue", c6);
			Assert.AreEqual("TrueTrueTrueTrueTrueTrueTrue", c7);
			Assert.AreEqual("mv2", c8);
			Assert.AreEqual("v6v6v6dv6", c9);
			Assert.AreEqual("v7dv7", c10);
			Assert.AreEqual("dv8v8dv8v8mv8dv8", c11);
		}

		[TestMethod]
		public void CacheDisposable()
		{
			string c1 = null;

			var hostName = Environment.MachineName.ToLower().SubstringTo(".");

			var res = SPH.RunUnder("http://localhost:777/",
								   delegate
								   {
									   var w0 = SPH.GetWeb();
									   SPWeb w1 = null;

									   using (
										   var d1 = new ManagedDisposable<SPWeb>("rw",
																				 () =>
																				 new ManagedDisposableInfo
																				   {
																					   Keys = new[] { "rw", "rootweb" },
																					   Disposable = w1 =
																									SPH.GetSite().AllWebs[w0.ID],
																					   ShouldBeDisposed = true
																				   }))
									   {
										   c1 = d1.Disposable.Url.ToLower().Replace(hostName, "localhost");

										   using (
											   var d2 = new ManagedDisposable<SPWeb>("rootweb",
																					 () =>
																					 new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw", "rootweb" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   c1 += "|" + d2.Disposable.Url.ToLower().Replace(hostName, "localhost");

											   c1 += "|" + ReferenceEquals(d1.Disposable, d2.Disposable);

											   c1 += "|" + d2.Info.UseCount + "|" + d2.Info.RefCount;
										   }

										   c1 += "|" + d1.Info.UseCount + "|" + d1.Info.RefCount;

										   var count = 0;

										   using (
											   var d3 = new ManagedDisposable<SPWeb>("rw3",
																					 () =>
																					 new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw3" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d3.Info.UseCount;
										   }

										   using (
											   var d4 = new ManagedDisposable<SPWeb>("rw4",
																					 () =>
																					 new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw4" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d4.Info.UseCount;
										   }

										   using (
											   var d5 = new ManagedDisposable<SPWeb>("rw5",
																					 () =>
																					 new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw5" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d5.Info.UseCount;
										   }

										   using (
											   var d6 = new ManagedDisposable<SPWeb>("rw6",
																					 () =>
																					 new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw6" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d6.Info.UseCount;
										   }

										   using (
											   var d7 = new ManagedDisposable<SPWeb>("rw7",
																					 () =>
																					 new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw7" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d7.Info.UseCount;
										   }

										   using (
											   var d8 = new ManagedDisposable<SPWeb>("rw8",
																					 () =>
																					 new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw8" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d8.Info.UseCount;
										   }

										   using (
											   var d9 = new ManagedDisposable<SPWeb>("rw9",
																					 () =>
																					 new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw9" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d9.Info.UseCount;
										   }

										   using (
											   var d10 = new ManagedDisposable<SPWeb>("rw10",
																					  () =>
																					  new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw10" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d10.Info.UseCount;
										   }

										   using (
											   var d11 = new ManagedDisposable<SPWeb>("rw11",
																					  () =>
																					  new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw11" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d11.Info.UseCount;
										   }

										   using (
											   var d12 = new ManagedDisposable<SPWeb>("rw12",
																					  () =>
																					  new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw12" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d12.Info.UseCount;
										   }

										   using (
											   var d13 = new ManagedDisposable<SPWeb>("rw13",
																					  () =>
																					  new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw13" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d13.Info.UseCount;
										   }

										   using (
											   var d14 = new ManagedDisposable<SPWeb>("rw14",
																					  () =>
																					  new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw14" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d14.Info.UseCount;
										   }

										   using (
											   var d15 = new ManagedDisposable<SPWeb>("rw15",
																					  () =>
																					  new ManagedDisposableInfo
																					   {
																						   Keys = new[] { "rw15" },
																						   Disposable =
																							   SPH.GetSite().AllWebs[w0.ID],
																						   ShouldBeDisposed = true
																					   }))
										   {
											   count += d15.Info.UseCount;
										   }

										   c1 += "|" + count;
										   c1 += "|" + ManagedDisposableCache.GetList().Count;
									   }

									   try
									   {
										   c1 += "|" + w1.Url.ToLower().Replace(hostName, "localhost");

										   if (w1.IsRootWeb)
											   w1.Users.Add("test1", "e@mail.ru", "test1", "");

										   w1.Delete();
									   }
									   catch (InvalidOperationException)
									   {
										   c1 += "|ioex";
									   }
									   catch (Exception)
									   {
										   c1 += "|ex";
									   }
								   });

			Assert.AreEqual(true, res, "SPH.RunUnder completed with errors!");

			Assert.AreEqual("http://localhost:777|http://localhost:777|True|2|2|2|1|13|10|http://localhost:777|ioex", c1);
		}
	}
}